package bg.code.commons.plugin.ui.table;

import bg.code.commons.builder.dto.ResultDTO;
import bg.code.commons.builder.utils.Strings;
import bg.code.commons.builder.vo.GenerateConfig;
import bg.code.commons.builder.vo.MethodDescriptor;
import bg.code.commons.plugin.ui.model.CustomCellEditor;
import bg.code.commons.plugin.ui.model.MethodTableModel;
import com.intellij.ui.components.JBPanel;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.components.JBTextField;
import com.intellij.ui.table.JBTable;

import javax.swing.*;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
import java.awt.*;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static bg.code.commons.plugin.Cons.*;

/**
 * @author 郑兴泉 956607644@qq.com
 * @data 2020/8/11
 * 描述：
 */
public final class MethodParamJBPanel implements ICustomJBPanel<JBTable> {

    private final JBTable table;
    private final List<MethodTableModel.MethodParamTable> headerCellName = new ArrayList<>(10);
    private String baseUrl;
    private final GenerateConfig generateConfig;
    private final String permissionNamePrev;

    public MethodParamJBPanel(GenerateConfig generateConfig) {
        this.generateConfig = generateConfig;
        this.baseUrl = generateConfig.getBaseUri();
        this.table = new JBTable();
        this.table.setShowGrid(true);
        this.table.setShowVerticalLines(false);
        this.table.setRowHeight(30);
        this.table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
        this.permissionNamePrev = conversionPermissionName();
        initData();
        this.table.setModel(new MethodTableModel(headerCellName));
        addTableModelListener();
        changeTableCellAttribute();
    }

    private String conversionPermissionName() {
        String permissionName = "";
        if (Strings.isNotBlank(this.baseUrl)) {
            permissionName =
                    this.baseUrl.replaceAll("^\\/", "")
                            .replaceAll("\\/$", "")
                            .replaceAll("\\/", ".");
        }
        return permissionName;
    }

    private void initData() {
        headerCellName.add(new MethodTableModel.MethodParamTable(INDEX_METHOD_NAME, "index", "index", Strings.join("/", baseUrl, "index"), Strings.join(".", permissionNamePrev, "index")));
        headerCellName.add(new MethodTableModel.MethodParamTable(LIST_METHOD_NAME, "doList", "data", Strings.join("/", baseUrl, "data"), Strings.join(".", permissionNamePrev, "data")));
        headerCellName.add(new MethodTableModel.MethodParamTable(SAVE_METHOD_NAME, "doSave", "save", Strings.join("/", baseUrl, "save"), Strings.join(".", permissionNamePrev, "save")));
        headerCellName.add(new MethodTableModel.MethodParamTable(EDIT_METHOD_NAME, "doUpdate", "update", Strings.join("/", baseUrl, "update"), Strings.join(".", permissionNamePrev, "update")));
        headerCellName.add(new MethodTableModel.MethodParamTable(DELETE_METHOD_NAME, "doDelete", "delete", Strings.join("/", baseUrl, "delete"), Strings.join(".", permissionNamePrev, "delete")));
        headerCellName.add(new MethodTableModel.MethodParamTable(ENABLED_METHOD_NAME, "doEnable", "enable", Strings.join("/", baseUrl, "enable"), Strings.join(".", permissionNamePrev, "enable")));
        headerCellName.add(new MethodTableModel.MethodParamTable(DISABLED_METHOD_NAME, "doDisabled", "disabled", Strings.join("/", baseUrl, "disabled"), Strings.join(".", permissionNamePrev, "disabled")));
        headerCellName.add(new MethodTableModel.MethodParamTable(EXPORT_METHOD_NAME, "doExport", "export", Strings.join("/", baseUrl, "export"), Strings.join(".", permissionNamePrev, "export")));
    }


    @Override
    public JComponent getComponent() {

        JBPanel panel = new JBPanel(new BorderLayout());
        panel.add(this.table);
        JScrollPane pane = new JBScrollPane(panel);


        JBPanel jPanel = new JBPanel(new BorderLayout());
        jPanel.setBorder(BorderFactory.createTitledBorder(METHOD_ANNOTATION_INFO));
        // 把 表头 添加到容器顶部（使用普通的中间容器添加表格时，表头 和 内容 需要分开添加）
        jPanel.add(table.getTableHeader(), BorderLayout.NORTH);
        // 把 表格内容 添加到容器中心
        jPanel.add(pane, BorderLayout.CENTER);
        return jPanel;
    }

    @Override
    public JBTable getObj() {
        return table;
    }


    @Override
    public List<MethodDescriptor> getData() {
        List<MethodDescriptor> methodDescriptors = new ArrayList<>(10);
        TableModel model = this.table.getModel();
        for (int row = 0, rowLen = model.getRowCount(); row < rowLen; row++) {
            Object value = model.getValueAt(row, 2);
            if (value != null) {
                Boolean autoGen = Boolean.parseBoolean(value.toString());
                if (Boolean.TRUE.equals(autoGen)) {
                    methodDescriptors.add(
                            new MethodDescriptor(
                                    Strings.sNull(model.getValueAt(row, 3)),
                                    Strings.sNull(model.getValueAt(row, 4)),
                                    Strings.sNull(model.getValueAt(row, 5)),
                                    Strings.sNull(model.getValueAt(row, 6))
                            ));
                }
            }
        }
        return methodDescriptors;
    }

    @Override
    public ResultDTO errorMsg() {
        TableModel model = this.table.getModel();
        Map<String, Boolean> map = new HashMap<>(10);
        for (int row = 0, rowLen = model.getRowCount(); row < rowLen; row++) {
            for (int cell = 2, cellLen = model.getColumnCount(); cell < cellLen; cell++) {
                Object value = model.getValueAt(row, cell);
                if (value != null) {
                    map.putIfAbsent(String.format("%s_%s_%s", row, cell, value.toString()), true);
                } else {
                    return new ResultDTO(true, "");
                }
            }
        }
        return new ResultDTO(true, "");
    }

    private void addTableModelListener() {
        // 在 表格模型上 添加 数据改变监听器
        TableModel model = this.table.getModel();
        model.addTableModelListener(new TableModelListener() {
            @Override
            public void tableChanged(TableModelEvent e) {
                // 获取 第一个 和 最后一个 被改变的行（只改变了一行，则两者相同）
                int firstRow = e.getFirstRow();
                int lastRow = e.getLastRow();
                int type = e.getType();
                int column = e.getColumn();
                // 事件的类型，可能的值有:
                //     TableModelEvent.INSERT   新行或新列的添加
                //     TableModelEvent.UPDATE   现有数据的更改
                //     TableModelEvent.DELETE   有行或列被移除
                if (type == TableModelEvent.UPDATE || type == TableModelEvent.INSERT) {
                    if (column < 4 || column > 4) {
                        return;
                    }
                    for (int row = firstRow; row <= lastRow; row++) {
                        Object methodRequestPath = model.getValueAt(row, 4);
                        if (methodRequestPath != null) {
                            // 全请求路径名称
                            model.setValueAt(MessageFormat.format("{0}/{1}", getBaseUrl(), methodRequestPath), row, 5);
                        }

//                    // 权限标识名称
//                    tableModel.setValueAt(methodRequestPath + ":" + methodRequestPath, row, 6);
                    }
                }
            }
        });
    }

    private void changeTableCellAttribute() {
        int headersLength = table.getColumnCount();
        TableColumnModel columnModel = table.getColumnModel();
        CustomCellEditor customTextFieldCellEditor = new CustomCellEditor(new JBTextField());
        for (int i = 0; i < headersLength; ++i) {
            TableColumn tableColumn = columnModel.getColumn(i);
            tableColumn.sizeWidthToFit();
            Class clazz = table.getColumnClass(i);
            if (!"java.lang.Boolean".equals(clazz.getName())) {
                tableColumn.setCellEditor(customTextFieldCellEditor);
            }
        }
    }

    public String getBaseUrl() {
        return baseUrl;
    }

    public void setBaseUrl(String baseUrl) {
        this.baseUrl = baseUrl;
    }
}

